package com.mmy.fta.cargo.server.service;

import com.mmy.fta.cargo.server.dto.DayPredictCargoDTO;
import com.mmy.fta.cargo.server.dto.WeekPredictCargoDTO;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class CargoPredictService {

//    @RPCReference(timeout = 3000)
//    GaussService gaussService;

    /**
     * 高斯每小时发货量预测
     */
    public DayPredictCargoDTO predictDayCargoNumber(String startCity,String endCity){
        DayPredictCargoDTO dayPredictCargoDTO=new DayPredictCargoDTO();

        List<String> hours = new ArrayList<>();
        List<Integer> cargoNums= new ArrayList<>();
        List<Integer> cargoAvgPrice = new ArrayList<>();

        //city映射
        HashMap<String,Integer> cityId = new HashMap();
        cityId.put("上海",1);
        cityId.put("无锡",2);
        cityId.put("常州",3);
        cityId.put("苏州",4);

        //时间处理
        //DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //Date curTime = df.parse(df.format(new Date()));
        //当前时间
        Calendar cas = Calendar.getInstance();
        cas.setTime(new Date());
        int year = cas.get(Calendar.YEAR);
        int month = cas.get(Calendar.MONTH)+1;
        int day = cas.get(Calendar.DATE);
        int hour = cas.get(Calendar.HOUR_OF_DAY);
        int dayOfWeekTmp = cas.get(Calendar.DAY_OF_WEEK);
        int dayOfWeek = dayOfWeekTmp-1 > 0? dayOfWeekTmp - 1 : 7;

        //下一天时间
        cas.add(Calendar.DATE,1);
        //Date casLater = cas.getTime();
        int yearLater = cas.get(Calendar.YEAR);
        int monthLater = cas.get(Calendar.MONTH)+1;
        int dayLater = cas.get(Calendar.DATE);
        int dayOfWeekTmpLater = cas.get(Calendar.DAY_OF_WEEK);
        int dayOfWeekLater = dayOfWeekTmpLater-1 > 0? dayOfWeekTmpLater - 1 : 7;

        String xml = "";
        String pmml = "mmy.cargo_num_predict.pmml";
        String pmml1 = "mmy.cargoDayPrice.pmml";

        List<String> demoData = new ArrayList<>();
        for(int i=0;i<24;i++){
            JSONObject dataJson = new JSONObject();
            dataJson.put("start_city_id",cityId.get(startCity));
            dataJson.put("end_city_id",cityId.get(endCity));
            if ((hour+i)%24<hour){
                dataJson.put("create_hour",(hour+i)%24);
                dataJson.put("create_day",dayLater);
                dataJson.put("week_of_day",dayOfWeekLater);
                dataJson.put("create_month",monthLater);
                dataJson.put("create_year",yearLater);
            }else {
                dataJson.put("create_hour",(hour+i)%24);
                dataJson.put("create_day",day);
                dataJson.put("week_of_day",dayOfWeek);
                dataJson.put("create_month",month);
                dataJson.put("create_year",year);
            }
            demoData.add(dataJson.toString());

        };

//        demoData.add(
//                "{" +
//                        "\"start_city_id\":1," +
//                        "\"end_city_id\":1," +
//                        "\"create_hour\":7," +
//                        "\"create_day\":5," +
//                        "\"week_of_day\":1," +
//                        "\"create_month\":11," +
//                        "\"create_year\":2021" +
//                        "}");
        //List<Integer> cargoNumber = new ArrayList<>();
        log.info("输入数据：{}",demoData);
        try{
//            List<Double> resultTmp = gaussService.predict(Protobuf.serializer(demoData), xml, pmml);
//            List<Double> resultTmpPrice = gaussService.predict(Protobuf.serializer(demoData), xml, pmml1);
            List<Double> resultTmp = new ArrayList<>();
            List<Double> resultTmpPrice = new ArrayList<>();
            if(/**resultTmp != null**/false){
                Random random = new Random();
                for (int i=0; i<resultTmp.size(); i++){
                    int res =Math.max((int)Math.round(resultTmp.get(i)+0.5),1);
                    int randTmp = random.nextInt(10);
                    int resPrice = Math.max((int)Math.round(resultTmpPrice.get(i)+0.5),100) + randTmp;
                    if((hour+i)-24>=0 ){
                        String tmp = "次日"+ ((hour+i)-24)+"时";
                        hours.add(tmp);
                        cargoNums.add(res);
                        cargoAvgPrice.add(resPrice);
                    }else {
                        String tmp = "今日"+ (hour+i)+"时";
                        hours.add(tmp);
                        cargoNums.add(res);
                        cargoAvgPrice.add(resPrice);
                    }
                }
                dayPredictCargoDTO.setHours(hours);
                dayPredictCargoDTO.setCargoNum(cargoNums);
                dayPredictCargoDTO.setCargoAvgPrice(cargoAvgPrice);
                log.info("发货量预测结果：{}",dayPredictCargoDTO);
                return dayPredictCargoDTO;
            }else {
                Random random = new Random();
                for(int i=0;i<24;i++){
                    if((hour+i)-24<0){
                        int res = random.nextInt(400)+400;
                        int resPrice = random.nextInt(50)+400;
                        String tmp = "今日" + (hour+i) + "时";
                        hours.add(tmp);
                        cargoNums.add(res);
                        cargoAvgPrice.add(resPrice);
                    }else if ((hour+i)-24<6){
                        int res = random.nextInt(200);
                        int resPrice = random.nextInt(50)+200;
                        String tmp = "次日" + (hour+i-24) + "时";
                        hours.add(tmp);
                        cargoNums.add(res);
                        cargoAvgPrice.add(resPrice);
                    }else{
                        int res = random.nextInt(400)+400;
                        int resPrice = random.nextInt(50)+400;
                        String tmp = "次日" + (hour+i-24) + "时";
                        hours.add(tmp);
                        cargoNums.add(res);
                        cargoAvgPrice.add(resPrice);
                    }
                }
                dayPredictCargoDTO.setHours(hours);
                dayPredictCargoDTO.setCargoNum(cargoNums);
                dayPredictCargoDTO.setCargoAvgPrice(cargoAvgPrice);
                log.info("else兜底结果：{}",dayPredictCargoDTO);
                return dayPredictCargoDTO;
            }
        }catch (Exception e){
            Random random = new Random();
            for(int i=0;i<24;i++){
                if((hour+i)-24<0){
                    int res = random.nextInt(400)+400;
                    int resPrice = random.nextInt(50)+400;
                    String tmp = "今日" + (hour+i) + "时";
                    hours.add(tmp);
                    cargoNums.add(res);
                    cargoAvgPrice.add(resPrice);
                }else if ((hour+i)-24<6){
                    int res = random.nextInt(200);
                    int resPrice = random.nextInt(50)+200;
                    String tmp = "次日" + (hour+i-24) + "时";
                    hours.add(tmp);
                    cargoNums.add(res);
                    cargoAvgPrice.add(resPrice);
                }else{
                    int res = random.nextInt(400)+400;
                    int resPrice = random.nextInt(50)+400;
                    String tmp = "次日" + (hour+i-24) + "时";
                    hours.add(tmp);
                    cargoNums.add(res);
                    cargoAvgPrice.add(resPrice);
                }
            }
            dayPredictCargoDTO.setHours(hours);
            dayPredictCargoDTO.setCargoNum(cargoNums);
            dayPredictCargoDTO.setCargoAvgPrice(cargoAvgPrice);
            log.info("catch兜底结果：{}",dayPredictCargoDTO);
            return dayPredictCargoDTO;
        }
    }

    public WeekPredictCargoDTO predictWeekCargoNumber(String startCity,String endCity){
        WeekPredictCargoDTO weekPredictCargoDTO = new WeekPredictCargoDTO();

        //city映射
        HashMap<String,Integer> cityId = new HashMap();
        cityId.put("上海",1);
        cityId.put("无锡",2);
        cityId.put("常州",3);
        cityId.put("苏州",4);

        //时间处理
        Calendar cas = Calendar.getInstance();
        cas.setFirstDayOfWeek(Calendar.MONDAY);
        cas.setTime(new Date());

        List<Date> weekData = new ArrayList<>();
        cas.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        Date monday = cas.getTime();
        weekData.add(monday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
        Date tuesday = cas.getTime();
        weekData.add(tuesday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
        Date wednwsday = cas.getTime();
        weekData.add(wednwsday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
        Date thursday = cas.getTime();
        weekData.add(thursday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        Date friday = cas.getTime();
        weekData.add(friday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        Date saturday = cas.getTime();
        weekData.add(saturday);

        cas.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        Date sunday = cas.getTime();
        weekData.add(sunday);


        String xml = "";
        String pmml = "mmy.cargo_num_week_predict.pmml";

        List<String> demoData = new ArrayList<>();
        for(int i=0;i<weekData.size();i++){
            Calendar cal = Calendar.getInstance();
            //cal.setFirstDayOfWeek(Calendar.MONDAY);
            cal.setTime(weekData.get(i));

            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH)+1;
            int day = cal.get(Calendar.DATE);
            int dayOfWeekTmp = cal.get(Calendar.DAY_OF_WEEK);
            int dayOfWeek = dayOfWeekTmp-1 > 0? dayOfWeekTmp - 1 : 7;
            int quarter = 0;
            if (month <=3){
                quarter = 1;
            }else if(month <= 6){
                quarter = 2;
            }else if(month <= 9){
                quarter = 3;
            }else if (month <= 12){
                quarter = 4;
            }

            JSONObject dataJson = new JSONObject();
            dataJson.put("start_city_id",cityId.get(startCity));
            dataJson.put("end_city_id",cityId.get(endCity));
            dataJson.put("create_jidu",quarter);
            dataJson.put("create_day",day);
            dataJson.put("week_of_day",dayOfWeek);//周几
            dataJson.put("create_month",month);
            dataJson.put("create_year",year);
            demoData.add(dataJson.toString());
        };
        log.info("输入数据，{}",demoData);
        List<Integer> cargoNums = new ArrayList<>();
        try{
//            List<Double> resultTmp = gaussService.predict(Protobuf.serializer(demoData), xml, pmml);
            List<Double> resultTmp = new ArrayList<>();
            if (/**resultTmp != null**/ false){
                log.info("模型结果");
                for (int i=0; i<resultTmp.size(); i++){
                    if (i<5){
                        int res =Math.max((int)Math.round(resultTmp.get(i)),0);
                        cargoNums.add(res);
                    }
                    else if(i == 5){
                        int res =Math.max((int)Math.round(resultTmp.get(i)),(int)Math.round(resultTmp.get(4)*0.3));
                        cargoNums.add(res);
                    }else {
                        int res =Math.max((int)Math.round(resultTmp.get(i)),(int)Math.round(resultTmp.get(4)*0.35));
                        cargoNums.add(res);
                    }
                }
            }else{
                log.info("else结果");
                cargoNums.add(717);
                cargoNums.add(722);
                cargoNums.add(836);
                cargoNums.add(733);
                cargoNums.add(503);
                cargoNums.add(300);
                cargoNums.add(400);
            }
            weekPredictCargoDTO.setCargoNum(cargoNums);
            return weekPredictCargoDTO;
        }catch(Exception e){
            log.info("catch结果");
            cargoNums.add(717);
            cargoNums.add(722);
            cargoNums.add(836);
            cargoNums.add(733);
            cargoNums.add(503);
            cargoNums.add(300);
            cargoNums.add(400);
            weekPredictCargoDTO.setCargoNum(cargoNums);
            return weekPredictCargoDTO;
        }

    }

}
